#ifndef __WAIT_H__
#define __WAIT_H__

#include "stddef.h"
#include "datasturcture.h"

typedef struct waitQueue_t waitQueue_t;
typedef struct wait_t wait_t;

typedef struct proc_t proc_t;  // TODO

struct waitQueue_t {
    list_entry_t wait_head;
};

struct wait_t {
    proc_t* proc;
    uint32_t wakeupFlags;
    waitQueue_t* waitQueue;
    list_entry_t waitLink;
};

#define le2wait(le, member) to_struct((le), wait_t, member)

void wait_init(wait_t* wait, proc_t* proc);
void waitQueue_init(waitQueue_t* q);
void waitQueue_add(waitQueue_t* q, wait_t* wait);
void waitQueue_del(waitQueue_t* q, wait_t* wait);

wait_t* waitQueue_next(waitQueue_t* q, wait_t* wait);
wait_t* waitQueue_prev(waitQueue_t* q, wait_t* wait);
wait_t* waitQueue_first(waitQueue_t* q);
wait_t* waitQueue_last(waitQueue_t* q);

bool waitQueue_isEmpty(waitQueue_t* q);
bool wait_isInQueue(wait_t* wait);
void wakeup_wait(waitQueue_t* q, wait_t* wait, uint32_t wakeupFlags, bool del);
void wakeup_first(waitQueue_t* q, uint32_t wakeupFlags, bool del);
void wakeup_queue(waitQueue_t* q, uint32_t wakeupFlags, bool del);

void wait_current_set(waitQueue_t* q, wait_t* wait, uint32_t waitState);

#define wait_current_del(q, wait) \
    if (wait_isInQueue(wait))       \
    waitQueue_del(q, wait)

#endif